/*
音频频谱与波形图
*/
package
{
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.BlendMode;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.TimerEvent;
	import flash.filters.BitmapFilterQuality;
	import flash.filters.BlurFilter;
	import flash.filters.ColorMatrixFilter;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	import flash.media.SoundMixer;
	import flash.utils.ByteArray;
	import flash.utils.Timer;
	
	public class Spectrum extends Sprite
	{	
		private var s:Sprite = new Sprite();
		private var Main:Sprite ;	
		private var spectrum:ByteArray = new ByteArray();
		private var currentStyle:String;
		private var timer:Timer;
		
		private var m_width:Number;
		private var m_height:Number;
		
		public function Spectrum(_width:Number = 200,_height:Number = 100)
		{
			addChild(s);
			m_width = _width;
			m_height = _height;	
					
			prismatical(_width,_height);
			//waveform(_width,_height);
		}
		
		//画柱状_Start///////////////////////////////////////////////////////////////////////////////////////
		private function prismatical(_width:Number,_height:Number):void{
			currentStyle = "prismatical";	
			
			Main = new Sprite();
			s.addChild(Main);
			for(var i:uint = 0; i<64 ; i++){
				var r:Rect = new Rect(5,_height);
				r.y = 0;
				r.x = 6 * i;
				Main.addChild(r);
				r.name = "r_" + i;
			}
			Main.width = _width;				
			if(!SoundMixer.areSoundsInaccessible()){
				timer = new Timer(200);
				timer.addEventListener(TimerEvent.TIMER,prismatical_update);
				timer.start();
			}
			
			//点击热区
			var a:Sprite = new Sprite();
			s.addChild(a);
			a.graphics.beginFill(0x000000,0);
			a.graphics.drawRect(0,0,_width,_height);
			a.graphics.endFill();			
			
		}
		
		private function prismatical_update(e:Event):void{
			
			SoundMixer.computeSpectrum(spectrum,true);
			for(var i:uint = 0; i < 64; i++){
				var a:Number = 0.0;
				spectrum.position = i * 16;
				a = spectrum.readFloat() + spectrum.readFloat() + spectrum.readFloat() + spectrum.readFloat();
				
				spectrum.position = 1024 + i * 16;
				a += spectrum.readFloat() + spectrum.readFloat() + spectrum.readFloat() + spectrum.readFloat();				
				var r:Rect = Rect(Main.getChildByName("r_" + i));
			
				r.update(a / 6);
			}			
		}	
		//画柱状_End///////////////////////////////////////////////////////////////////////////////////////
		//画波形图 Start///////////////////////////////////////////////////////////////////////////////////
		private function waveform(_width:Number,_height:Number):void{
			currentStyle = "waveform";
			var line:Sprite=new Sprite();
			var bmpData:BitmapData = new BitmapData(_width,_height,true,0x999999);
			var bmp:Bitmap = new Bitmap(bmpData);		
			
			//声明一个BlurFilter滤镜
        	var blur:BlurFilter = new BlurFilter(7,7,BitmapFilterQuality.LOW);
			var n:Number = 0;        	
        	var r:Rectangle=new Rectangle(0,0,_width,_height);
        	var p:Point=new Point(0,0);        	
        	var colorM:ColorMatrixFilter=new ColorMatrixFilter([0.9,0,0,0,0,
														        0,0.9,0,0,0,
														        0,0,0.9,0,0,
														        0,0,0,0.68,0,
														        ]);
			Main = new Sprite();
			Main.blendMode=BlendMode.ADD;

			s.addChild(Main);
			Main.addChild(bmp);
			Main.addChild(line);			 			
			if(!SoundMixer.areSoundsInaccessible()){
				timer = new Timer(80);
				timer.addEventListener(TimerEvent.TIMER,waveform_update);
				timer.start();
			}
			function waveform_update(e:TimerEvent):void{
				 n = 0;
		        //这里是为了每2次才执行一次滤镜而做的if,如果需要让原来的波形图消失的更慢就把2改成更大的数字
		    	if(timer.currentCount%2==0){
		        	//将Main的内容绘制到bmpData		        	
		        	bmpData.draw(Main);
		        	//应用滤镜
		        	bmpData.applyFilter(bmpData,r,p,colorM);
		       		bmpData.applyFilter(bmpData,r,p,blur);
		        }		       
		        //清除绘图
		        line.graphics.clear();
		        //设置线条样式,颜色湖蓝,宽度1,透明度100
		        line.graphics.lineStyle(1,0x2AEAEB,100);	        
		        
		        SoundMixer.computeSpectrum(spectrum);
		        //左声道
		        for(var i:uint=0; i < 256; i+=2){
		                //在ByteArray中读取一个32位的单精度浮点数(这个是livedoc上写的,实际就是把数据流读取成浮点数)
		                n = spectrum.readFloat();
		                //为了平滑,隔着读
		               	spectrum.readFloat();//spectrum.position += 4;
		                //这个实际作用是把n扩大一下
		               // n = n*_height;
		                //如果i不为0
		                if(i!=0){
		                //画波形图
		                line.graphics.lineTo(i * _width / 256,_height * (n + 3)/ 6 );
		                }else{
		                //移动    
		                line.graphics.moveTo(0,_height * (n + 3)/ 6);
		                }
		        }
		        //右声道
		        for(i=0; i < 256; i+=2){
		               
		                n = spectrum.readFloat();
		               		spectrum.readFloat();//spectrum.position += 4;
		               
		                if(i!=0){		               
		              		line.graphics.lineTo(i * _width / 256,_height * (n + 3) / 6);
		                }else{		                  
		               		line.graphics.moveTo(0,_height * (n + 3)/ 6);
		                }
		        }
			}
		}	
		//画波形图 End///////////////////////////////////////////////////////////////////////////////////
		
		public function changeStyle():void{
			timer.stop();
			while(s.numChildren>0)s.removeChildAt(0);
			if(currentStyle == "waveform"){
				prismatical(m_width,m_height);
			}else{
				waveform(m_width,m_height);
			}
		}
	}
}


//内部调用
//柱体类
import flash.display.Sprite;
import flash.utils.Timer;
import flash.events.TimerEvent;
	

class Rect extends Sprite{
	private var s:Sprite; //柱状体
	private var zsp:Sprite; //柱状体上的小方块
	private var timer:Timer;
	private var h:Number;
	
	public function Rect(_width:Number,_height:Number,color:uint = 0x666666){
		s = new Sprite();
		
		//画柱状体
		s.graphics.beginFill(color);
		s.graphics.drawRect(0,0,_width,_height);
		s.graphics.endFill();
		
		//旋转180度柱体才会从上往下降
		s.rotation = 180;
		s.height = 0;
		s.y = _height;
		addChild(s);
		
		h = _height;//记录最高长度
		
		var zHeight:Number = 2;//块状体高
		zsp = new Sprite();
		zsp.graphics.beginFill(0x2AEAEB);
		zsp.graphics.drawRect(0,0,_width,zHeight);
		zsp.graphics.endFill();
		zsp.y = _height - zHeight;
		zsp.rotation = 180;
		addChild(zsp);
		
		timer = new Timer(40);
		timer.addEventListener(TimerEvent.TIMER,onTimer);
		timer.start();
	}	
	
	
	
	private function onTimer(e:TimerEvent):void{
		if(s.height > 0){
			var speed:Number = 0.02 * h;//柱状体下降的速度
			if(speed > s.height)s.height = 0;
			else s.height -= speed;		
		}
		if(zsp.y + zsp.height >= h - s.height){
			zsp.y = h - s.height - zsp.height;
		}
		else{
			var zspeed:Number = 0.01 * h;
			zsp.y += zspeed;
		}
				
	}
	
	//更新柱体的高度,仅只当设置的高度比当前的高度还要高的时候才更新.
	public function update(percent:Number):void{
		if(percent>1.0) percent = 1.0;		
		
		if(s.height < h * percent){
			s.height = h * percent;
			if(zsp.y + zsp.height >= h - s.height){
			zsp.y = h - s.height - zsp.height;
			}
		}		
	}
}
